package com.qdlc.p2p.biz.service.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.qdlc.p2p.biz.executer.AbstractExecuter;
import com.qdlc.p2p.biz.executer.ExecuterHelper;
import com.qdlc.p2p.biz.executer.impl.UserModifyPayPwdExecuter;
import com.qdlc.p2p.biz.executer.impl.UserModifyPwdExecuter;
import com.qdlc.p2p.biz.log.score.BaseScoreLog;
import com.qdlc.p2p.biz.log.score.identify.EmailScoreLog;
import com.qdlc.p2p.biz.log.score.login.RegisteScoreLog;
import com.qdlc.p2p.biz.service.UserIdentifyService;
import com.qdlc.p2p.biz.service.UserService;
import com.qdlc.p2p.biz.service.UserStatisticsService;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.exception.AccountException;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.exception.TppChinapnrException;
import com.qdlc.p2p.common.exception.UserException;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.MessageUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.util.code.BASE64Decoder;
import com.qdlc.p2p.common.util.code.MD5;
import com.qdlc.p2p.dal.common.model.jpa.PageDataList;
import com.qdlc.p2p.dal.common.model.jpa.QueryParam;
import com.qdlc.p2p.dal.dao.AccountDao;
import com.qdlc.p2p.dal.dao.MemberInfosDao;
import com.qdlc.p2p.dal.dao.ScoreDao;
import com.qdlc.p2p.dal.dao.TppMemberAgentDao;
import com.qdlc.p2p.dal.dao.UserCacheDao;
import com.qdlc.p2p.dal.dao.UserCreditDao;
import com.qdlc.p2p.dal.dao.UserDao;
import com.qdlc.p2p.dal.dao.UserIdentifyDao;
import com.qdlc.p2p.dal.dao.UserInviteDao;
import com.qdlc.p2p.dal.dao.UserLoginDao;
import com.qdlc.p2p.dal.dao.UserLoginExtDao;
import com.qdlc.p2p.dal.dao.UserVipDao;
import com.qdlc.p2p.dal.dto.Account;
import com.qdlc.p2p.dal.dto.MemberAgent;
import com.qdlc.p2p.dal.dto.MemberInfos;
import com.qdlc.p2p.dal.dto.Score;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserCache;
import com.qdlc.p2p.dal.dto.UserCredit;
import com.qdlc.p2p.dal.dto.UserIdentify;
import com.qdlc.p2p.dal.dto.UserInvite;
import com.qdlc.p2p.dal.dto.UserLoginExt;
import com.qdlc.p2p.dal.dto.UserVip;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.UserModel;
import com.qdlc.p2p.dal.util.UserUtils;

@Service("userService")
public class UserServiceImpl implements UserService {

	private static Map<String, String> userCheckMap;

	static {
		userCheckMap = Maps.newConcurrentMap();
	}

	@Resource
	private UserDao userDao;

	@Resource
	private UserLoginDao userLoginDao;

	@Resource
	private UserLoginExtDao userLoginExtDao;

	@Resource
	private UserIdentifyDao userIdentifyDao;

	@Resource
	private UserCacheDao userCacheDao;

	@Resource
	private AccountDao accountDao;

	@Resource
	private UserCreditDao userCreditDao;

	@Resource
	private UserIdentifyService userIdentifyService;

	@Resource
	private ScoreDao scoreDao;

	@Resource
	private UserInviteDao userInviteDao;

	@Resource
	private UserVipDao userVipDao;

	@Resource
	private MemberInfosDao memberInfosDao;

	@Resource
	private TppMemberAgentDao tppMemberAgentDao;

	@Resource
	private UserStatisticsService userStatisticsService;

	@Override
	public User find(long userId) {
		return userDao.findObjByProperty("userId", userId);
	}

	@Override
	public User findByTppId(String tppId) {
		return userDao.findObjByProperty("tppUserCustId", tppId);
	}

	@Override
	public int countByUserName(String userName) {
		return userDao.countByUserName(userName);
	}

	@Override
	public User getUserByUserName(String userName) {
		return userDao.findObjByProperty("userName", userName);
	}

	@Override
	public int count(QueryParam param) {
		return userDao.countByCriteria(param);
	}

	@Override
	public int countByCardId(String cardId) {
		return userDao.countByCardId(cardId);
	}

	@Override
	public int countByMobilePhone(String mobilePhone) {
		return userDao.countByMobilePhone(mobilePhone);
	}

	@Override
	public int countByEmail(String email) {
		return userDao.countByEmail(email);
	}

	@Override
	public User getUserByEmail(String email) {
		return userDao.findObjByProperty("email", email);
	}

	@Override
	public User getUserByMobilePhone(String mobilePhone) {
		return userDao.getUserByMobilePhone(mobilePhone);
	}

	@Override
	public User doRegister(UserModel model) {
		return doRegister(model, false);
	}

	@Override
	public User doRegister(UserModel model, boolean partnerFlg) {
		User user = model.prototype();
		if ((user.getMobilePhone() != null) && !"".equals(user.getMobilePhone())) {
			int hasMobilePhone = userDao.countByMobilePhone(user.getMobilePhone());
			if (hasMobilePhone > 0) {
				throw new UserException("手机已经被使用", 1);
			}
		}

		int hasUsername = userDao.countByUserName(user.getUserName());
		if (hasUsername > 0) {
			throw new UserException("用户名已经被使用", 1);
		}

		if (!(StringUtil.isBlank(userCheckMap.get(user.getUserName()))
				&& StringUtil.isBlank(userCheckMap.get(user.getMobilePhone())))) {
			throw new UserException("手机或用户名已被使用", 1);
		}
		userCheckMap.put(user.getUserName(), "1");
		userCheckMap.put(user.getMobilePhone(), "1");
		// 合作者调用 则密码不需要编码 注册时间由调用方提供
		if (partnerFlg == false) {
			user.setPwd(MD5.encode(user.getPwd()));
			user.setAddTime(DateUtil.getNow());
		}

		// 登录扩展表
		UserLoginExt userLoginExt = new UserLoginExt(user);
		// 用户名插入
		userLoginExt.setUserName(user.getUserName());
		userLoginExt.setAddTime(user.getAddTime());
		userLoginExt.setIsDelete(0);
		userLoginExtDao.save(userLoginExt);

		// 手机号插入
		userLoginExt = new UserLoginExt(user);
		userLoginExt.setUserName(user.getMobilePhone());
		userLoginExt.setAddTime(user.getAddTime());
		userLoginExtDao.save(userLoginExt);

		// 用户附属信息
		UserCache uc = new UserCache(user, Global.getIP());
		// 投资人默认用户性质为公司
		// 1:投资人/2:借款人/3:投资借款人'
		/*
		 * if (model.getIsCompany() == 1 && (model.getUserType() == 2 || model.getUserType() == 3)) {
		 * // 用户性质 1:自然人,2:公司法人(公司注册),3:担保账户'
		 * uc.setUserNature(2);
		 * } else {
		 * uc.setUserNature(1);
		 * }
		 */
		// 1:投资人/2:借款人/3:投资借款人'
		uc.setUserType(model.getUserType());
		uc.setUserNature(model.getUserNature());
		if (partnerFlg == true) {
			uc.setIsImp(1);
		}
		uc.setAvatarPicPath("/avatar/01-png"); // 默认头像
		userCacheDao.save(uc);
		// 用户认证信息
		userIdentifyDao.save(new UserIdentify(user.getUserId()));
		// 资金账户
		accountDao.save(new Account(user.getUserId()));
		// 用户amount
		userCreditDao.save(new UserCredit(user));
		// 添加用户积分信息
		Score score = new Score(user);
		scoreDao.save(score);
		if (model.getUserType() != 1) {
			// 企业信息表
			MemberInfos mi = new MemberInfos();
			mi.setUserId(user.getUserId());
			memberInfosDao.save(mi);
			// 经办人信息表
			MemberAgent ma = new MemberAgent();
			ma.setUser(user);
			tppMemberAgentDao.save(ma);
		}
		BaseScoreLog bLog = new RegisteScoreLog(score.getId(), user.getUserId());
		bLog.doEvent();
		if (model.getUserType() != 2) {
			// 添加用户vip信息
			userVipDao.save(new UserVip(user));
		}
		// 初化化user_statistics 信息 用户统计信息
		userStatisticsService.init(user);

		User inviteUser = model.getInviteUser();
		if (inviteUser != null) {
			UserInvite iu = new UserInvite();
			iu.setInviteTime(DateUtil.getNow());
			iu.setUserId(user.getUserId());
			iu.setInviteUser(inviteUser.getUserId());
			userInviteDao.insert(iu);
		}
		userCheckMap.remove(user.getUserName());
		userCheckMap.remove(user.getMobilePhone());
		return user;
	}

	@Override
	public User activationEmail(String idstr) throws Exception {
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] idstrBytes = decoder.decodeBuffer(idstr);
		String decodeidstr = new String(idstrBytes);
		String[] idstrArr = decodeidstr.split(",");
		if (idstrArr.length < 4) {
			throw new UserException("链接无效，请重新获取邮件！");
		}
		long activeTime = StringUtil.toLong(idstrArr[2]);
		// long vtime = StringUtil.toLong(Global.getString("verify_code_time"));
		if ((System.currentTimeMillis() - (activeTime * 1000)) > (24 * 60 * 60 * 1000)) {
			throw new UserException("链接有效时间为一天，该链接已过期，请重新获取激活邮件!", "/");
		}
		String useridStr = idstrArr[0];
		long userId = Long.parseLong(useridStr);
		User user = userDao.findObjByProperty("userId", userId);
		UserIdentify userIdentify = userIdentifyDao.findObjByProperty("user.userId", userId);
		if (userIdentify.getEmailStatus() == 1) {
			if (StringUtil.isNotBlank(user.getPwd())) {
				throw new UserException("您的邮箱已激活，不必重复激活！", "login.html");
			}
		} else {
			userIdentifyDao.modifyEmailStatus(userId, 1, 0);
			BaseScoreLog bLog = new EmailScoreLog(userId);
			bLog.doEvent();
		}
		return user;
	}

	@Override
	public User modifyPwd(User user) {
		int is_imp = 2;
		UserCache userCache = UserUtils.getUserCacheByUserId(user.getUserId());
		if (userCache.getIsImp() == 0) {
			is_imp = 0;
		}
		userCacheDao.modifyPwdTime(user.getUserId(), is_imp);
		Global.setTransfer("noticeTime", DateUtil.getTime(DateUtil.getNow()));
		Global.setTransfer("user", user);
		AbstractExecuter executer = ExecuterHelper.getExecuter(UserModifyPwdExecuter.class);
		executer.execute(0, user);
		user.setPwd(MD5.encode(user.getPwd()));
		userLoginDao.modifyPwd(user); // 修改密码
		return userDao.modifyPwd(user);
	}

	@Override
	public User modifyPaypwd(User user) {
		Global.setTransfer("noticeTime", DateUtil.getTime(DateUtil.getNow()));
		Global.setTransfer("user", user);
		AbstractExecuter executer = ExecuterHelper.getExecuter(UserModifyPayPwdExecuter.class);
		executer.execute(0, user);
		user.setPayPwd(MD5.encode(user.getPayPwd()));// 支付密码
		userLoginDao.modifyPaypwd(user); // 修改支付密码
		return userDao.modifyPaypwd(user);
	}

	@Override
	public User getPwdByEmailStep1(HttpServletRequest request, String userName, String email) {
		User user = userDao.findObjByProperty("email", email);
		if (user == null) {
			throw new UserException("该邮箱不存在！");
		}
		// BaseAccountLog blog = new GetCodeLog(user, user.getUserName(), NoticeConstant.NOTICE_GET_PWD_EMAIL);
		// blog.initCode("get_pwd_email");
		// blog.doEvent();
		return user;
	}

	@Override
	public PageDataList<UserModel> userList(int pageNumber, int pageSize, UserModel model) {
		return userDao.userList(pageNumber, pageSize, model);
	}

	@Override
	public List<User> getVouchFirms() {
		return userDao.getVouchFirms();
	}

	@Override
	public PageDataList<User> findUserList(BorrowModel model) {
		return userDao.findUserList(model);
	}

	@Override
	public User getUserByInfo(String username) {
		User user = getUserByUserName(username);
		if (user == null) {
			user = getUserByMobilePhone(username);
		}
		if (user == null) {
			user = getUserByEmail(username);
		}
		return user;
	}

	@Override
	public User getUserById(long userId) {
		return userDao.find(userId);
	}

	@Override
	public void update(User user) {
		userDao.merge(user);
	}

	@Override
	public void tppchinapnrRegis(long userId, String tppUserId, String tppUserCustId, String cardId, String realName) {
		User user = userDao.find(userId);
		if (null == user) {
			throw new TppChinapnrException(MessageUtil.getMessage("MF104001003"));
		}
		String userCustId = UserUtils.getUserTppCustId(userId);
		if (StringUtils.isNotBlank(userCustId)) {
			return;
		}
		UserIdentify identify = userIdentifyDao.findByUserId(user.getUserId());
		identify.setRealNameStatus(1);
		userIdentifyDao.update(identify);
		user.setCardId(cardId);
		user.setRealName(realName);
		user.setTppUserCustId(tppUserCustId);
		userDao.update(user);
	}

	@Override
	public User save(User user) {
		return userDao.save(user);
	}

	@Override
	public User loginForApp(String userName, String pwd) {
		User u = userDao.findObjByProperty("mobilePhone", userName);
		if (u == null) {
			u = userDao.findObjByProperty("userName", userName);
		}
		if ((u != null) && !MD5.encode(pwd).equals(u.getPwd())) {
			u = null;
		}
		return u;
	}

	@Override
	public void tppAuditMemberInfosSuccess(String auditOrderNo, String innerOrderNo, byte auditStatus,
			String auditMessage) {

		QueryParam param = QueryParam.getInstance();
		param.addParam("auditOrderNo", auditOrderNo);
		MemberInfos memberInfos = memberInfosDao.findByCriteriaForUnique(param);
		if (null == memberInfos) {
			throw new TppChinapnrException(MessageUtil.getMessage("MF104001003"));
		}
		// 更新认证信息表
		UserIdentify identify = userIdentifyDao.findByUserId(memberInfos.getUserId());
		identify.setRealNameStatus(1);
		identify.setEmailStatus(1);
		userIdentifyDao.update(identify);
		// 更新企业信息表
		memberInfos.setInnerOrderNo(innerOrderNo);
		memberInfos.setStatus((byte) 1);
		// 更新用户表状态
		memberInfos.setAuditMessage(StringUtil.isNull(auditMessage));
		memberInfos.setUpdateTime(DateUtil.getNow());
		memberInfosDao.update(memberInfos);
	}

	@Override
	public void tppAuditMemberInfosFail(String auditOrderNo, String innerOrderNo, byte auditStatus,
			String auditMessage) {

		QueryParam param = QueryParam.getInstance();
		param.addParam("auditOrderNo", auditOrderNo);
		MemberInfos memberInfos = memberInfosDao.findByCriteriaForUnique(param);
		if (null == memberInfos) {
			throw new TppChinapnrException(MessageUtil.getMessage("MF104001003"));
		}
		if ("1".equals(memberInfos.getStatus())) {
			return;
		}
		// 更新企业信息表
		memberInfos.setInnerOrderNo(innerOrderNo);
		memberInfos.setStatus((byte) 2);
		memberInfos.setAuditMessage(StringUtil.isNull(auditMessage));
		memberInfos.setUpdateTime(DateUtil.getNow());
		memberInfosDao.update(memberInfos);
	}

	@Override
	public User getCurrentSessionUser(UserIdentify sessionUserIdentify) {
		if (sessionUserIdentify == null) {
			throw new AccountException("账户登录已失效，请重新登录!", "user/login.html");
		}
		UserIdentify userIdentify = userIdentifyService.findById(sessionUserIdentify.getId());
		if (userIdentify == null) {
			throw new AccountException("账户登录已失效，请重新登录!", "user/login.html");
		}
		User user = UserUtils.getUserById(userIdentify.getUserId());
		if (user == null) {
			throw new AccountException("账户登录已失效，请重新登录!", "user/login.html");
		}
		return user;
	}

	@Override
	public User getCurrentSessionUser4Json(UserIdentify sessionUserIdentify) {
		if (sessionUserIdentify == null) {
			throw new AccountException("账户登录已失效，请重新登录!", BusinessException.TYPE_JSON);
		}
		UserIdentify userIdentify = userIdentifyService.findById(sessionUserIdentify.getId());
		if (userIdentify == null) {
			throw new AccountException("账户登录已失效，请重新登录!", BusinessException.TYPE_JSON);
		}
		User user = UserUtils.getUserById(userIdentify.getUserId());
		if (user == null) {
			throw new AccountException("账户登录已失效，请重新登录!", BusinessException.TYPE_JSON);
		}
		return user;
	}

	@Override
	public List<UserModel> userListForExcel(int start, int itemCount, UserModel model) {
		return userDao.userListForExcel(start, itemCount, model);
	}

	@Override
	public int getCountByUserCondition(UserModel model) {
		return userDao.getCountByUserCondition(model);
	}

	@Override
	public int getRegisterCountByDate(String date) {
		return userDao.getRegisterCountByDate(date);
	}
}
